'use client';

import type {
  IPostEditInfo,
  IPostNewInfo,
  IUploadPostCover,
  IUploadPostCoverBody,
  IUploadPostNewFile,
  IUploadPostNewFileBody,
} from '@/interfaces';
import { type ChangeEvent, useContext, useState } from 'react';
import { PostEditContext } from '@/contexts/post-edit';
import { getCover } from '@/lib/tool';
import { useMutation } from '@tanstack/react-query';
import type { TBody } from '@/types';
import {
  updatePostEditInfo,
  uploadPostCover,
  uploadPostNewFile,
} from '@/services/api';
import { AppContext } from '@/contexts/app';
import useToast from '@/hooks/useToast';
import Image from 'next/image';

export type TCoverTranslatedField =
  | 'update'
  | 'coverPlaceholder'
  | 'upload'
  | 'uploadCompleted'
  | 'updateCompleted';

export default function Cover({
  source,
  translatedFields = {
    update: '更新',
    coverPlaceholder: '请输入封面链接',
    upload: '上传',
    uploadCompleted: '上传完成',
    updateCompleted: '更新完成',
  },
}: {
  source: IPostEditInfo | IPostNewInfo;
  translatedFields?: Record<TCoverTranslatedField, any>;
}) {
  const appContent = useContext(AppContext);
  const metadata = appContent.metadata!;
  const context = useContext(PostEditContext);
  const { form, setForm } = context;
  const isEdit = 'basic' in source;
  const [customForm, setCustomForm] = useState({
    uploadCover: '',
    uploadCoverFile: '',
    uploadCoverObjectUrl: '',
  });
  const { show } = useToast();

  const uploadPostCoverMutation = useMutation(
    async (variables: TBody<IUploadPostCoverBody>) => {
      return (await uploadPostCover(variables)) as IUploadPostCover;
    },
  );
  const uploadPostNewCoverMutation = useMutation(
    async (variables: TBody<IUploadPostNewFileBody>) => {
      return (await uploadPostNewFile(variables)) as IUploadPostNewFile;
    },
  );
  const updatePostEditInfoMutation = useMutation(updatePostEditInfo);

  async function onClickUpdate() {
    if (!isEdit) {
      show({
        type: 'SUCCESS',
        message: translatedFields.updateCompleted,
      });
      return;
    }

    try {
      const _form: any = {
        cover: form.cover,
      };

      await updatePostEditInfoMutation.mutateAsync({
        id: source.basic.id,
        data: _form,
      });
    } catch (e) {
      updatePostEditInfoMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickUploadCover() {
    try {
      const file = customForm.uploadCoverFile;
      if (!file) {
        return;
      }

      let result;
      if (isEdit) {
        result = await uploadPostCoverMutation.mutateAsync({
          id: source.basic.id,
          data: { file },
        });
      } else {
        result = await uploadPostNewCoverMutation.mutateAsync({
          data: { file },
        });
      }

      setForm({
        ...form,
        cover: result.urls.default,
      });

      show({
        type: 'SUCCESS',
        message: translatedFields.uploadCompleted,
      });
    } catch (e) {
      if (isEdit) {
        uploadPostCoverMutation.reset();
      } else {
        uploadPostNewCoverMutation.reset();
      }

      show({
        type: 'DANGER',
        message: e,
      });
    } finally {
      if (customForm.uploadCoverObjectUrl) {
        URL.revokeObjectURL(customForm.uploadCoverObjectUrl);
      }

      setCustomForm((prevState) => {
        prevState.uploadCoverObjectUrl = '';
        prevState.uploadCoverFile = '';
        prevState.uploadCover = '';
        return prevState;
      });
    }
  }

  function onChange(
    e: ChangeEvent<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'uploadCover') {
      if (customForm.uploadCoverObjectUrl) {
        URL.revokeObjectURL(customForm.uploadCoverObjectUrl);
      }

      const file = (e.target as any).files[0];
      const objectUrl = URL.createObjectURL(file);
      setCustomForm({
        ...customForm,
        uploadCover: value,
        uploadCoverFile: file,
        uploadCoverObjectUrl: objectUrl,
      });
    } else {
      setForm({
        ...form,
        [name]: value,
      });
    }
  }

  return (
    <div className="card border-0">
      <div className="card-body d-flex flex-column gap-4 my-4">
        <textarea
          name="cover"
          value={form.cover}
          onChange={onChange}
          className="form-control"
          rows={1}
          placeholder={translatedFields.coverPlaceholder}
        />

        <div className="input-group">
          <input
            type="file"
            accept="image/*"
            className="form-control"
            name="uploadCover"
            value={customForm.uploadCover}
            onChange={onChange}
          />
          <button
            disabled={
              isEdit
                ? uploadPostCoverMutation.isLoading
                : uploadPostNewCoverMutation.isLoading
            }
            onClick={onClickUploadCover}
            className="btn btn-outline-secondary"
            type="button"
          >
            {(isEdit
              ? uploadPostCoverMutation.isLoading
              : uploadPostNewCoverMutation.isLoading) && (
              <span
                className="spinner-border spinner-border-sm me-2"
                role="status"
                aria-hidden="true"
              ></span>
            )}
            {translatedFields.upload}
          </button>
        </div>

        {(customForm.uploadCoverObjectUrl || form.cover) && (
          <div className="hstack gap-4">
            <div className="ratio ratio-16x9">
              <Image
                width={142}
                height={80}
                src={
                  customForm.uploadCoverObjectUrl
                    ? customForm.uploadCoverObjectUrl
                    : getCover(form.cover, metadata)
                }
                alt="cover"
                className="object-fit-contain"
              />
            </div>
            <div className="ratio ratio-16x9">
              <Image
                width={260}
                height={146}
                src={
                  customForm.uploadCoverObjectUrl
                    ? customForm.uploadCoverObjectUrl
                    : getCover(form.cover, metadata)
                }
                alt="cover"
                className="object-fit-contain"
              />
            </div>
            <div className="ratio ratio-16x9">
              <Image
                width={378}
                height={213}
                src={
                  customForm.uploadCoverObjectUrl
                    ? customForm.uploadCoverObjectUrl
                    : getCover(form.cover, metadata)
                }
                alt="cover"
                className="object-fit-contain"
              />
            </div>
          </div>
        )}

        <div className="d-grid col-2">
          <button
            onClick={onClickUpdate}
            type="button"
            className="btn btn-success"
          >
            {translatedFields.update}
          </button>
        </div>
      </div>
    </div>
  );
}
